﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using ShareMarking.Entity;
using ShareMarking.Service;
using System.Security.Cryptography;

namespace ShareMarking.Interface
{
    public class Qrcode_vigo
    {
        //var httpstr = "http://my.erpcoo.com/index.php/Api/Qrcode/index";
        //var httpstr = "http://test.erpcoo.cn/index.php/Api/Qrcode/index";

        protected string httpstr;
        protected string signserect;
        /// <summary>
        /// 默认参数
        /// </summary>
        public Dictionary<string, UrlPars_Model> defaultPars;

        public bool ParamOrder = true; //参数需要排序
        public string Key = "sdf5sf5et5e42t5"; //商家密钥
        public string codeType = "utf-8"; //gb2312

        public Qrcode_vigo(string httpstr, string signserect)
        {
            this.httpstr = httpstr;
            this.signserect = signserect;
        }
        
        public result CreateQrcode(string message)
        {
            #region sign 已弃用
            //var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");

            //var parameters = new Dictionary<string, string>();
            //parameters.Add("message", ComLib.JsonHelper.JsonSerializer<message>(message));
            //parameters.Add("method", "001");
            //parameters.Add("timestamp", timestamp);

            //var request_str = BuildQuery(parameters) + this.signserect;
            //var signature = ComLib.DEncrypt.MD5ForPHP(request_str.ToLower());
            //parameters.Add("sign", signature);
            #endregion

            #region sign2
            var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");
            defaultPars = new Dictionary<string, UrlPars_Model>();

            UrlPars_Model param1 = new UrlPars_Model();
            param1.IsSign = true; //参数需要签名
            param1.IsUrlCode = false; //参数需要URLEncode
            param1.IsMinType = false; //参数需要转成小写
            param1.ParsName = "method"; //参数名
            param1.ParsValue = "001"; //参数值

            defaultPars.Add(param1.ParsName, param1);

            UrlPars_Model param2 = new UrlPars_Model();
            param2.IsSign = true; //参数需要签名
            param2.IsUrlCode = true; //参数需要URLEncode
            param2.IsMinType = true; //参数需要转成小写
            param2.ParsName = "message"; //参数名
            param2.ParsValue =message;//"{\"title\":\"TestQrCodeOne\",\"remark\":\"Test\",\"sacode\":\"\",\"scene_id\":9993,\"extra\":[{\"title\":\"标题\",\"shortdesc\":\"图文简介\",\"picurl\":\"http://img15.3lian.com/2016/w4/48/69.jpg\",\"linkurl\":\"https://www.baidu.com/\"}]}"; //参数值

            defaultPars.Add(param2.ParsName, param2);

            UrlPars_Model param3 = new UrlPars_Model();
            param3.IsSign = true; //参数需要签名
            param3.IsUrlCode = false; //参数需要URLEncode
            param3.IsMinType = false; //参数需要转成小写
            param3.ParsName = "timestamp"; //参数名
            param3.ParsValue = timestamp;//"2016-07-27 23:32:42"; //参数值

            defaultPars.Add(param3.ParsName, param3);
            string signature = GetSign();

            UrlPars_Model param4 = new UrlPars_Model();
            param4.IsSign = true; //参数需要签名
            param4.IsMinType = false; //参数需要转成小写
            param4.ParsName = "sign"; //参数名
            param4.ParsValue = signature;//"2016-07-27 23:32:42"; //参数值

            defaultPars.Add(param4.ParsName, param4);//生成秘钥
            #endregion

            var pst = NewBuildQuery2(defaultPars).ToString();
            var postData = Encoding.UTF8.GetBytes(pst);
            ComLib.WebClientHelper click = new ComLib.WebClientHelper();
            click.Encoding = Encoding.UTF8;
            string result = click.Post(this.httpstr, postData);//请求处理，返回结果
            var resultentity = ComLib.JsonHelper.JsonDeserialize<ShareMarking.Entity.result>(result);

            return resultentity;
        }


        public result CreateQrcode(message message)
        {
            #region sign 已弃用
            //var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");

            //var parameters = new Dictionary<string, string>();
            //parameters.Add("message", ComLib.JsonHelper.JsonSerializer<message>(message));
            //parameters.Add("method", "001");
            //parameters.Add("timestamp", timestamp);

            //var request_str = BuildQuery(parameters) + this.signserect;
            //var signature = ComLib.DEncrypt.MD5ForPHP(request_str.ToLower());
            //parameters.Add("sign", signature);
            //    var pst = BuildQuery2(parameters).ToString();
              #endregion
                     
            #region sign2
            var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");
            defaultPars = new Dictionary<string, UrlPars_Model>();
            UrlPars_Model param1 = new UrlPars_Model();
            param1.IsSign = true; //参数需要签名
            param1.IsUrlCode = false; //参数需要URLEncode
            param1.IsMinType = false; //参数需要转成小写
            param1.ParsName = "method"; //参数名
            param1.ParsValue = "001"; //参数值
            defaultPars.Add(param1.ParsName, param1);

            UrlPars_Model param2 = new UrlPars_Model();
            param2.IsSign = true; //参数需要签名
            param2.IsUrlCode = true; //参数需要URLEncode
            param2.IsMinType = true; //参数需要转成小写
            param2.ParsName = "message"; //参数名
            param2.ParsValue = ComLib.JsonHelper.JsonSerializer<message>(message);//"{\"title\":\"TestQrCodeOne\",\"remark\":\"Test\",\"sacode\":\"\",\"scene_id\":9993,\"extra\":[{\"title\":\"标题\",\"shortdesc\":\"图文简介\",\"picurl\":\"http://img15.3lian.com/2016/w4/48/69.jpg\",\"linkurl\":\"https://www.baidu.com/\"}]}"; //参数值
            defaultPars.Add(param2.ParsName, param2);

            UrlPars_Model param3 = new UrlPars_Model();
            param3.IsSign = true; //参数需要签名
            param3.IsUrlCode = false; //参数需要URLEncode
            param3.IsMinType = false; //参数需要转成小写
            param3.ParsName = "timestamp"; //参数名
            param3.ParsValue = timestamp;//"2016-07-27 23:32:42"; //参数值
            defaultPars.Add(param3.ParsName, param3);

            string signature = GetSign();

            UrlPars_Model param4 = new UrlPars_Model();
            param4.IsSign = true; //参数需要签名
            param4.IsMinType = false; //参数需要转成小写
            param4.ParsName = "sign"; //参数名
            param4.ParsValue = signature;//"2016-07-27 23:32:42"; //参数值
            defaultPars.Add(param4.ParsName, param4);//生成秘钥
            #endregion

            var pst = NewBuildQuery2(defaultPars).ToString();
            var postData = Encoding.UTF8.GetBytes(pst);//HttpUtility.UrlEncode(pst)
            ComLib.WebClientHelper click = new ComLib.WebClientHelper();
            click.Encoding = Encoding.UTF8;
            string result = click.Post(this.httpstr, postData);//请求处理，返回结果
            var resultentity= ComLib.JsonHelper.JsonDeserialize<ShareMarking.Entity.result>(result);
            
            return resultentity;
        }

        public string UpdateQrcode(message2 message)
        {
            #region sign 已弃用
            //var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");
            //var parameters = new Dictionary<string, string>();
            //parameters.Add("message", ComLib.JsonHelper.JsonSerializer<message2>(message));
            //parameters.Add("method", "002");
            //parameters.Add("timestamp", timestamp);

            //var request_str = BuildQuery(parameters) + this.signserect;
            //var signature = ComLib.DEncrypt.MD5ForPHP(request_str.ToLower());
            //parameters.Add("sign", signature);
            #endregion

            #region sign
            var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");
            defaultPars = new Dictionary<string, UrlPars_Model>();

            UrlPars_Model param1 = new UrlPars_Model();
            param1.IsSign = true; //参数需要签名
            param1.IsUrlCode = true; //参数需要URLEncode
            param1.IsMinType = true; //参数需要转成小写
            param1.ParsName = "method"; //参数名
            param1.ParsValue = "002"; //参数值

            defaultPars.Add(param1.ParsName, param1);

            UrlPars_Model param2 = new UrlPars_Model();
            param2.IsSign = true; //参数需要签名
            param2.IsUrlCode = true; //参数需要URLEncode
            param2.IsMinType = true; //参数需要转成小写
            param2.ParsName = "message"; //参数名
            param2.ParsValue = ComLib.JsonHelper.JsonSerializer<message2>(message);//"{\"title\":\"TestQrCodeOne\",\"remark\":\"Test\",\"sacode\":\"\",\"scene_id\":9993,\"extra\":[{\"title\":\"标题\",\"shortdesc\":\"图文简介\",\"picurl\":\"http://img15.3lian.com/2016/w4/48/69.jpg\",\"linkurl\":\"https://www.baidu.com/\"}]}"; //参数值
           
            defaultPars.Add(param2.ParsName, param2);

            UrlPars_Model param3 = new UrlPars_Model();
            param3.IsSign = true; //参数需要签名
            //param3.IsUrlCode = true; //参数需要URLEncode
            param3.IsMinType = true; //参数需要转成小写
            param3.ParsName = "timestamp"; //参数名
            param3.ParsValue = timestamp;//"2016-07-27 23:32:42"; //参数值

            defaultPars.Add(param3.ParsName, param3);

            string signature = GetSign();

            UrlPars_Model param4 = new UrlPars_Model();
            param4.IsSign = true; //参数需要签名
            param4.IsMinType = true; //参数需要转成小写
            param4.ParsName = "sign"; //参数名
            param4.ParsValue = signature;//"2016-07-27 23:32:42"; //参数值

            defaultPars.Add(param4.ParsName, param4);//生成秘钥

            #endregion

            var pst = NewBuildQuery2(defaultPars).ToString();
            var postData = Encoding.UTF8.GetBytes(pst);//HttpUtility.UrlEncode(pst)
            ComLib.WebClientHelper click = new ComLib.WebClientHelper();
            click.Encoding = Encoding.UTF8;
            string result = click.Post(this.httpstr, postData);

            return result;
        }

        public result_qrlog GetUsedCount(int page)
        {
            #region sign 已弃用
            //var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");
            //var parameters = new Dictionary<string, string>();
            //parameters.Add("message", "{\"startdate\":\"" + "2016-03-0512:05:00" 
            //    + "\",\"enddate\":\"" + "2016-05-2000:00:00"
            //     + "\",\"pageno\":\"" + page
            //      + "\",\"pagesize\":\"" + "2000"
            //      + "\"}");
            //parameters.Add("method", "003");
            //parameters.Add("timestamp", timestamp);

            //var request_str = BuildQuery(parameters) + this.signserect;
            //var signature = ComLib.DEncrypt.MD5ForPHP(request_str.ToLower());
            //parameters.Add("sign", signature);
            #endregion

            #region sign
            var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");
            defaultPars = new Dictionary<string, UrlPars_Model>();

            UrlPars_Model param1 = new UrlPars_Model();
            param1.IsSign = true; //参数需要签名
            param1.IsUrlCode = false; //参数需要URLEncode
            param1.IsMinType = false; //参数需要转成小写
            param1.ParsName = "method"; //参数名
            param1.ParsValue = "003"; //参数值
            defaultPars.Add(param1.ParsName, param1);

            UrlPars_Model param2 = new UrlPars_Model();
            param2.IsSign = true; //参数需要签名
            param2.IsUrlCode = true; //参数需要URLEncode
            param2.IsMinType = true; //参数需要转成小写
            param2.ParsName = "message"; //参数名
            int pagesize= 2000;
            param2.ParsValue = "{\"startdate\":\"" + "2016-01-1000:00:00"
                + "\",\"enddate\":\"" + "2016-07-2823:23:23"
                + "\",\"pageno\":" + page
                + ",\"pagesize\":" + pagesize
                + "}";
            defaultPars.Add(param2.ParsName, param2);

            UrlPars_Model param3 = new UrlPars_Model();
            param3.IsSign = true; //参数需要签名
            param3.IsUrlCode = false; //参数需要URLEncode
            param3.IsMinType = false; //参数需要转成小写
            param3.ParsName = "timestamp"; //参数名
            param3.ParsValue = timestamp;//"2016-07-27 23:32:42"; //参数值

            defaultPars.Add(param3.ParsName, param3);

            string signature = GetSign();

            UrlPars_Model param4 = new UrlPars_Model();
            param4.IsSign = true; //参数需要签名
            param4.IsMinType = false; //参数需要转成小写
            param4.ParsName = "sign"; //参数名
            param4.ParsValue = signature;

            defaultPars.Add(param4.ParsName, param4);//生成秘钥

            #endregion

            var pst = NewBuildQuery2(defaultPars).ToString();
            var postData = Encoding.UTF8.GetBytes(pst);
            ComLib.WebClientHelper click = new ComLib.WebClientHelper();
            click.Encoding = Encoding.UTF8;
            string result = click.Post(this.httpstr, postData);
            var resultentity = ComLib.JsonHelper.JsonDeserialize<ShareMarking.Entity.result_qrlog>(result);

            return resultentity;
        }

        public resultca GetWXContent(string code, string scene_id)
        {
            #region sign 已弃用
            //var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");

            //var parameters = new Dictionary<string, string>();
            //parameters.Add("message", "{\"code\":\"" + code + "\",\"scene_id\":\"" + scene_id + "\"}");
            //parameters.Add("method", "004");
            //parameters.Add("timestamp", timestamp);

            //var request_str = BuildQuery(parameters) + this.signserect;
            //var signature = ComLib.DEncrypt.MD5ForPHP(request_str.ToLower());
            //parameters.Add("sign", signature);
            #endregion

            #region sign
            var timestamp = DateTime.Now.ToString("yyyy-MM-ddHH:mm:ss");
            defaultPars = new Dictionary<string, UrlPars_Model>();

            UrlPars_Model param1 = new UrlPars_Model();
            param1.IsSign = true; //参数需要签名
            param1.IsUrlCode = false; //参数需要URLEncode
            param1.IsMinType = false; //参数需要转成小写
            param1.ParsName = "method"; //参数名
            param1.ParsValue = "004"; //参数值            
            //"{\"title\":\"TestQrCodeOne\",\"remark\":\"Test\",\"sacode\":\"\",\"scene_id\":9993,\"extra\":[{\"title\":\"标题\",\"shortdesc\":\"图文简介\",\"picurl\":\"http://img15.3lian.com/2016/w4/48/69.jpg\",\"linkurl\":\"https://www.baidu.com/\"}]}"; //参数值
            defaultPars.Add(param1.ParsName, param1);

            UrlPars_Model param2 = new UrlPars_Model();
            param2.IsSign = true; //参数需要签名
            param2.IsUrlCode = true; //参数需要URLEncode
            param2.IsMinType = true; //参数需要转成小写
            param2.ParsName = "message"; //参数名
            param2.ParsValue = "{\"code\":\"" + code + "\",\"scene_id\":" + Convert.ToInt32(scene_id) + "}"; //"{\"code\":\"" +  + "\",\"scene_id\":" + Convert.ToInt32(scene_id) + "}";
            defaultPars.Add(param2.ParsName, param2);

            UrlPars_Model param3 = new UrlPars_Model();
            param3.IsSign = true; //参数需要签名
            param3.IsUrlCode = false; //参数需要URLEncode
            param3.IsMinType = false; //参数需要转成小写
            param3.ParsName = "timestamp"; //参数名
            param3.ParsValue = timestamp;//"2016-07-27 23:32:42"; //参数值
            defaultPars.Add(param3.ParsName, param3);

            string signature = GetSign();

            UrlPars_Model param4 = new UrlPars_Model();
            param4.IsSign = true; //参数需要签名
            param4.IsUrlCode = false; //参数需要URLEncode
            param4.IsMinType = false; //参数需要转成小写
            param4.ParsName = "sign"; //参数名
            param4.ParsValue = signature;//"2016-07-27 23:32:42"; //参数值
            defaultPars.Add(param4.ParsName, param4);//生成秘钥

            #endregion

            //var pst = BuildQuery2(parameters).ToString();
            var pst = NewBuildQuery2(defaultPars).ToString();
            var postData = Encoding.UTF8.GetBytes(pst);
            ComLib.WebClientHelper click = new ComLib.WebClientHelper();
            click.Encoding = Encoding.UTF8;
            string result = click.Post(this.httpstr, postData);
            var resultentity = ComLib.JsonHelper.JsonDeserialize<ShareMarking.Entity.resultca>(result);

            return resultentity;
        }

        /// <summary>
        /// 获得签名
        /// </summary>
        /// <returns></returns>
        private string GetSign()
        {
            string sign = "";

            List<string> signList = new List<string>();

            foreach (UrlPars_Model model in defaultPars.Values)
            {
                if (model.IsSign)//问题1：需要问清楚，哪些参数需要参与签名
                {
                    signList.Add(model.ParsName);
                }
            }

            //参数需要排序//问题2:参数是否需要排序,暂且假如需要排序true
            if (ParamOrder)
            {
                signList.Sort();
            }

            //签名字符
            string signAllStr = string.Empty;

            string valueStr = string.Empty;
            foreach (string str in signList)
            {
                valueStr = string.Empty;
                valueStr = (defaultPars[str].ParsValue != null ? defaultPars[str].ParsValue : "");
                if (defaultPars[str].IsUrlCode && !string.IsNullOrEmpty(valueStr))
                {
                    if (defaultPars[str].IsMinType)//问题3:参数是否小写
                    {
                        valueStr = System.Web.HttpUtility.UrlEncode(valueStr).ToLower();
                    }
                    else
                    {
                        valueStr = System.Web.HttpUtility.UrlEncode(valueStr);
                    }
                }
                signAllStr = signAllStr + str + valueStr;
            }

            //当有商家密钥时也计算签名//问题4:商家密钥是什么
            if (!string.IsNullOrEmpty(this.signserect))
            {
                signAllStr = signAllStr + this.signserect.Trim();
            }

            //txtSign2.Text = signAllStr;

            //签名 MD5 加密
            if (!string.IsNullOrEmpty(signAllStr))
            {
                //问题5:编码方式，UTF-8，GB2312
                byte[] result = Encoding.GetEncoding(codeType).GetBytes(signAllStr);

                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] t = md5.ComputeHash(result);
                StringBuilder sb = new StringBuilder(32);
                for (int i = 0; i < t.Length; i++)
                {
                    sb.Append(t[i].ToString("x").PadLeft(2, '0'));
                }
                sign = sb.ToString();
            }
            return sign;
        }

        /// <summary>
        /// 组装普通文本请求参数。
        /// </summary>
        /// <param name="parameters">Key-Value形式请求参数字典</param>
        /// <returns>URL编码后的请求数据</returns>
        public static string BuildQuery(IDictionary<string, string> parameters)
        {
            StringBuilder postData = new StringBuilder();

            IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
            while (dem.MoveNext())
            {
                string name = dem.Current.Key;
                string value = dem.Current.Value;
                // 忽略参数名为空的参数
                if (!string.IsNullOrEmpty(name))
                {
                    postData.Append(name);
                    if (name == "message")
                    {
                        postData.Append(HttpUtility.UrlEncode(value, Encoding.UTF8));
                    }
                    else
                    {
                        postData.Append(value);
                    }
                }
            }
            return postData.ToString();
        }

        /// <summary>
        /// 组装普通文本请求参数。
        /// </summary>
        /// <param name="parameters">Key-Value形式请求参数字典</param>
        /// <returns>URL编码后的请求数据</returns>
        public static string BuildQuery2(IDictionary<string, string> parameters)
        {
            StringBuilder postData = new StringBuilder();
            bool hasParam = false;

            IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
            while (dem.MoveNext())
            {
                string name = dem.Current.Key;
                string value = dem.Current.Value;
                // 忽略参数名为空的参数
                if (!string.IsNullOrEmpty(name))
                {
                    if (hasParam)
                    {
                        postData.Append("&");
                    }

                    postData.Append(name);
                    postData.Append("=");
                    //if (name == "message")
                    //{
                    //    postData.Append(HttpUtility.UrlEncode(value));
                    //}
                    //else
                    //{
                    postData.Append(value);
                    //}
                    hasParam = true;
                }
            }

            return postData.ToString();
        }

        /// <summary>
        /// 组装普通文本请求参数。
        /// </summary>
        /// <param name="parameters">Key-Value形式请求参数字典</param>
        /// <returns>URL编码后的请求数据</returns>
        public static string NewBuildQuery2(IDictionary<string, UrlPars_Model> parameters)
        {
            StringBuilder postData = new StringBuilder();
            bool hasParam = false;

            IEnumerator<KeyValuePair<string, UrlPars_Model>> dem = parameters.GetEnumerator();
            while (dem.MoveNext())
            {
                string name = dem.Current.Value.ParsName;
                string value = dem.Current.Value.ParsValue;
                // 忽略参数名为空的参数
                if (!string.IsNullOrEmpty(name))
                {
                    if (hasParam)
                    {
                        postData.Append("&");
                    }

                    postData.Append(name);
                    postData.Append("=");
                    //if (name == "message")
                    //{
                    //    postData.Append(HttpUtility.UrlEncode(value));
                    //}
                    //else
                    //{
                    postData.Append(value);
                    //}
                    hasParam = true;
                }
            }

            return postData.ToString();
        }
    }

    /// <summary>
    /// URL 参数对象
    /// </summary>
    public class UrlPars_Model
    {
        private string parsName;

        /// <summary>
        /// 参数名
        /// </summary>
        public string ParsName
        {
            get { return parsName; }
            set { parsName = value; }
        }

        private string parsValue;

        /// <summary>
        /// 参数值
        /// </summary>
        public string ParsValue
        {
            get { return parsValue; }
            set { parsValue = value; }
        }
        private bool isSign;

        /// <summary>
        /// 是否参与签名
        /// </summary>
        public bool IsSign
        {
            get { return isSign; }
            set { isSign = value; }
        }

        private bool isUrlCode;

        /// <summary>
        /// 是否需要URL编码
        /// </summary>
        public bool IsUrlCode
        {
            get { return isUrlCode; }
            set { isUrlCode = value; }
        }

        private bool isNumber;

        /// <summary>
        /// 是否数字
        /// 0-数字，1-文字
        /// </summary>
        public bool IsNumber
        {
            get { return isNumber; }
            set { isNumber = value; }
        }

        private bool isMinType;

        /// <summary>
        /// 是否小写
        /// </summary>
        public bool IsMinType
        {
            get { return isMinType; }
            set { isMinType = value; }
        }
    }
}
